package com.astoolkit.workflow
{
	import com.astoolkit.workflow.api.ITasksGroup;
	import com.astoolkit.workflow.api.IWorkflowElement;
	import com.astoolkit.workflow.api.IWorkflowTask;

	internal class GroupUtil
	{
		internal static function getRuntimeTasks( inElements : Vector.<IWorkflowElement> ) : Vector.<IWorkflowTask>
		{
			return recursivelyFindMyTasks( addInserts( inElements ) );
		}
		
		private static function addInserts( inElements : Vector.<IWorkflowElement> ) : Vector.<IWorkflowElement>
		{
			var out : Vector.<IWorkflowElement> = inElements.concat();
			if( !inElements || inElements.length == 0 )
				return out;
			var thisParent : ITasksGroup = IWorkflowElement( inElements[0] ).parent;
			var aParent : ITasksGroup = thisParent;
			while( aParent != null )
			{
				for each( var insertEntry : Insert in aParent.insert )
				{
					var taskParent : ITasksGroup = insertEntry.parent;
					if( insertEntry.relativeTo != null )
						taskParent = insertEntry.relativeTo.parent;
					
					if( taskParent == thisParent )
					{
						var insertionPoint : int;
						if( insertEntry.relativeTo != null )
						{
							var i : int;
							for( i = 0; i < out.length; i++ )
							{
								if( insertEntry.relativeTo == out[ i ] )
								{
									break;
								}
							}
							insertionPoint = insertEntry.position == Insert.BEFORE ? i : i + 1;
						}
						else
						{
							// if children length == 0 we always add the task starting at 0,
							// otherwise depending on the position value we add 
							// to the beginning or end of the tasks array
							insertionPoint = out.length > 0 ?
								(insertEntry.position == Insert.BEFORE ? 0 : out.length ) : 0;
						}
						
						for each( var element : IWorkflowElement in insertEntry.tasks )
						{
							out.splice( insertionPoint, 0, element );
							insertionPoint++;
						}
					}
				}
				aParent = aParent.parent;
				
			}
			return out;
		}
		
		private static function recursivelyFindMyTasks( inElements : Vector.<IWorkflowElement> ) : Vector.<IWorkflowTask>
		{
			var out : Vector.<IWorkflowTask> = new Vector.<IWorkflowTask>();
			for each( var element : IWorkflowElement in inElements )
			{
				if( element is IWorkflowTask )
					out.push( element );
				else if( element is ITasksGroup )
					out = out.concat( getRuntimeTasks( ITasksGroup( element ).children ) );
			}
			return out;
		}

	}
}